Raça ou cor em São Paulo - uma leitura a partir dos microdados censitários

Spatial distribution
Race
Post description for first post
Author

Núcleo de Dados

Published

January 5, 2025

Intro

O presente texto explorará brevemente como acessar e manipular alguns dados sobre a questão racial na região central do município de São Paulo. Mais especificamente, o foco recairá sobre a distribuição espacial da população negra residente na região da Liberdade ao longo do tempo.

Para isso, dentre as diferentes bases disponíveis, optou-se por utilizar os dados do censo demográfico brasileiro, produzidos e disponibilizados pelo IBGE. Tal escolha reside na possibilidade de:

  • Replicar a análise para diferentes partes do território brasileiro (reprodutibilidade);

  • Realizar o resgate histórico da temática (cobertura temporal) e

  • Observar a distribuição do fenômeno espacial (cobertura espacial).

A análise proposta fará uso dos microdados censitários. Para uma versão similar baseada nos setores censitários, veja essa outra postagem (CRIAR LINK). Por fim, uma análise integrando ambos os dados, microdados e dados agregados por setor censitário, pode ser vista aqui (CRIAR LINK).

Antes da exploração proposta, vale mencionar que dois pilares conduzem a análise proposta: i) a busca por uma construção de caráter mais didático e não necessariamente extensiva1, e, ii) o uso das chamadas boas práticas para a manipulação de dados. Sem negar a importância da eficiência que as consultas e códigos devem perseguir, privilegia-se uma construção mais gradual, incremental e transparente - tarefa em muito facilitada pela concepção e ferramentas que compõem o Tidyverse. Ressalte-se, ainda, que um dos horizontes que guiam o presente esforço é o da Ciência Aberta.

Colocando a mão na massa: preparando o ambiente

Uma prática bastante usual ao escrever códigos no R consiste em “declarar/ativar” os pacotes (de funções) no início do script - por vezes isso também ocorre com as variáveis que serão utilizadas ao longo do percurso. Ainda que não seja obrigatória, essa prática permite que as funções sejam utilizadas sem que se explicite o nome do pacote (no R, para declarar o pacote e uma de suas funções segue-se a seguinte forma: pacote::função).

A seguir, duas formas para instalar e ativar os pacotes necessários são apresentadas. Gerando o mesmo resultado (ativação dos pacotes), a diferença entre a primeira forma (1st Way) e a segunda (2nd Way) é que na última o código checa os pacotes presentes no ambiente local/computador do usuário e apenas instala os que ainda não foram baixados. Já no primeiro caso, mesmo que o pacote já esteja instalado, o comando baixará novamente o seu conteúdo e o reinstalará. Note: para tornar mais claro o que está ocorrendo no segundo caminho de instalação, optou-se por inserir mensagens indicando se o pacote já estava instalado ou não (graças ao uso do comando print(“mensagem_a_ser_exibida”)). Observe, ainda, que o símbolo # é utilizado para a inserção de comentários no código, algo tido como uma boa prática. Ou seja, sempre que se fizer uso desse recurso, o conteúdo que vier imediatamente após ele será “ignorado”

Nota

O uso de comentários proporciona uma maior inteligibilidade do código e conversa diretamente com a possibilidade de reprodutibilidade do trabalho. Para exemplificar o ponto, pense que você e/ou outras pessoas podem revisitar o código no futuro e alguns detalhes podem não estar mais tão claros.

Code
# Save all the packages needed inside an object ("folder")
1pckgs <- c("tidyverse", "sf", "here", "janitor", "arrow", "censobr", "geobr", "sidrar", "gt", "devtools", "mapview", "terra", "patchwork", "RColorBrewer", "leafsync")

# 1st way 
## Install all the packages previously selected
2# install.packages(pckgs, dependencies = TRUE)

## Load the packages. This make all the packages functionalities available 
3# lapply(pckgs, library, character.only = TRUE)


# 2nd way
## Create a list with all the packages already installed
4pckgs_installed <- installed.packages()[,1]

# Install only the packages needed that are not in your computer yet
5for (pckgs_sel in pckgs) {
  print(paste("Checking if the package", pckgs_sel, "is installed"))
  if (!(pckgs_sel %in% pckgs_installed)) {
    install.packages(pckgs_sel, dependencies = TRUE)
    print(paste("The", pckgs_sel, "was installed"))
  } else {
  print(paste("The", pckgs_sel, "is already installed" ))}
}

# Load the packages
6lapply(pckgs, library, character.only = TRUE)
1
Selecione os pacotes necessários;
2
Instale os pacotes (1st way);
3
Ative os pacotes (1st way);
4
Identifique os pacotes já instalados no R (2nd way);
5
Cheque e instale apenas os pacotes que não estão em seu computador (2nd way);
6
Ative os pacotes de interesse (2nd way);

Obtendo e investigando os dados: usando os pacotes GEOBR e CENSOBR

Diferentes são os caminhos para acessar e manipular dados no R. A reconstrução manual da base dentro do próprio ambiente, com a transcrição de dados ainda não digitalizados, é um exemplo. Registre-se, porém, que quanto maior for o volume de dados, mais demorada e suscetível a erros será essa tarefa. Por esse motivo, costuma-se evitar esse tipo de abordagem.

Outra opção consiste em salvar um conjunto de dados já tabulado por alguma instituição (IBGE, IPEA, Fundação SEADE, CEM USP, etc.) em um computador pessoal e abri-lo no ambiente do R. O IBGE, por exemplo, disponibiliza diferentes recursos e plataformas com essa finalidade: i) a seção do site da instituição voltada aos censos demográficos; ii); o seu sistema de recuperação de informações, o SIDRA, ou, iii) o acesso ao servidor do IBGE via FTP.

Por fim, mas sem esgotar o assunto, o acesso a dados pode ser feito por meio de pacotes criados especificamente para esse fim. Com uma vasta gama de casos no R, este é o caminho que será explorado aqui. Mais especificamente, serão utilizados o CENSOBR, que fornece dados cenistários tabulares (tabelas), e o GEOBR, que disponibiliza dados geoespaciais. A partir desses de ambas as bases, os dados de interesse serão integrados, de forma a incorporar a dimensão territorial na análise.

Com vistas a tornar a presente exploração mais facilmente replicável a outros contextos, a seguir dois objetos são criados: i) um para definir a escala na qual a área de interesse está inserida - no presente caso, dado que a região de interesse é a Liberdade, o município de São Paulo será escolhido - e ii) o outro para o ano do censo de interesse. Iniciando a análise para o ano de 2010, com esse tipo de procedimento bastaria mudar duas informações, a escala e o ano, e todo o restante do código será gerado automaticamente, mas agora com novos dados.

Code
# Let's create a list of variables to reuse the code
## Select the municipality(ies)' name(s)
mun_name = "São Paulo"

## Select the census demographic year
census_year = 2010 # Possible years: 1960, 1970, 1980, 1991, 2000, 2010. See: https://ipeagit.github.io/censobr/articles/censobr.html

O próximo passo consiste em descobrir e escolher quais variáveis do censo retratam a questão e/ou o fenômeno a ser analisado (no presente caso, a raça/cor). Para isso, deve-se recorrer ao dicionário de variáveis.

Antes, porém, é importante relembrar que os dados censitários demográficos produzidos pelo IBGE são disponibilizados a partir de dois grandes tipos: os microdados (dados da amostra) e os agregados por setor censitário (dados do universo)2. Ambos os dados podem ser acessados por meio do pacote CENSOBR3, ainda que o foco da presente exploração baseie-se nos microdados, como anteriormente sinalizado.

Assim sendo, conforme ilustra o código a seguir, inicia-se com a escolha do tipo de dado que será analisado (neste caso, os microdados da amostra). Em seguida, o dicionário de variáveis será visitado para a identificação do tema/variáveis de interesse (no presente caso, a questão racial, retratada como cor ou raça).

Code
# Choose the variables
## Select the dataset of interest
1dataset_sel = "population"
# Para ver as possibilidades, digite  ?censobr::data_dictionary no console e veja o argumento "dataset". Ali podem ser vistas as bases disponibiizadas pelo pacote ("population", "households", "families", "mortality", "emigration", "tracts")

## See the variable dictionary
2data_dictionary(year = census_year, dataset = dataset_sel)
 # Possibilities: 1960, 1970, 1980, 1991, 2000, 2010. See: https://ipeagit.github.io/censobr/articles/censobr.html
1
Defina qual base dos microdados será utilizada;
2
Baixe o dicionário de variáveies da base selecionada;

Observando-se o dicionário de variáveis, algumas variáveis foram escolhidas (ver o quadro a seguir). Primando pela concisão, os critérios para a seleção foram a escala de interesse (V0011) e os limites político-administrativos do dado (V0001 e V0002); a geração da estimativa do número de pessoas (V0010); a possibilidade de ligação dessa base com as demais bases dos microdados (V0300) e, por fim, a inclusão da questão a ser analisada, raça (V0606), a qual se acrescentou o genêro (V0601).

Código das variáveis Nomenclatura
V0001 Unidade da Federação (UF)
V0002 Cód. do município
V0011 Área de ponderação
V0300 Variável de controle
V0010 Peso amostral
V0606 Raça ou Cor
V0601 Sexo
Code
# Choose the population variables of interest 
var_cens_pop <- c("V0001", "V0002", "V0011", "V0300", "V0010", "V0606", "V0601")

Escolhidas as variáveis, o passo seguinte consiste em obter os dados propriamente ditos (“baixá-los” para a sessão atual do R). Ao realizar essa tarefa, alguns avisos podem ser gerados. Não se preocupe, porém. A partir da leitura dos avisos, verifica-se que as mensagens geradas não se referem a um erro, mas sim a uma série de orientações padrão.

Registre-se, em tempo, que após realizar todo o procedimento de acesso e manipulação para o ano de 2010, adiante o mesmo caminho será replicado com os dados dos censos de 2000 e 1991.

Nota

Os dados da amostra do censo demográfico brasileiro costumam ser grandes e pesados, o que implica em um uso bastante intenso da memória RAM. Para lidar com esse comportamento do R (alocação dos dados na memória RAM), uma estratégia interessante é adotada pelo CENSOBR: preparar/estruturar o cômputo e gerá-lo apenas quando ele for explicitamente solicitado (mais detalhes podem ser vistos aqui).

Code
# Download and Select the variables of interest from POP MICRODATA, including RACE
micro_pop_orig <- read_population(year = census_year, columns = var_cens_pop) # 1) if the downloading was stopped before finishing, use "censobr::censobr_cache(delete_file = "2000_population_v0.3.0.parquet")" to exclude it from your computer before running the code again; 2) for the 2010 census, the argument 'add_labels = "pt"' transform the categories codes of variabels into its labels.
Code
# Compute the total population for the municipality, weighting area (AP) and household by race
## Select the municipality of interest and load the pop data
1micro_pop <- micro_pop_orig |>
2  filter(V0001 == "35" & V0002 == "50308") |>
3  collect() |>
  # mutate(V0624 = as.numeric(V0624)) |>
4  clean_names()

5glimpse(micro_pop)
1
Selecione a base de dados de interesse e crie um novo objeto para armazenar o resultado das operações a seguir;
2
Filtre os dados, escolhendo apenas os que se referem ao município de São Paulo;
3
“Traga” os dados para a sessão atual do R;
4
Uniformize o nome das variáveis (padrão adotado: letras mínusculas, com o espaço entre as palavras preenchido pelo símbolo “_”), e,
5
Observe o resultado gerado.
Rows: 552,037
Columns: 7
$ v0001 <chr> "35", "35", "35", "35", "35", "35", "35", "35", "35", "35", "35"…
$ v0002 <chr> "50308", "50308", "50308", "50308", "50308", "50308", "50308", "…
$ v0011 <chr> "3550308005001", "3550308005001", "3550308005001", "355030800500…
$ v0300 <dbl> 6965, 6965, 6965, 6965, 7117, 7117, 7117, 7117, 48707, 48707, 48…
$ v0010 <dbl> 12.9312, 12.9312, 12.9312, 12.9312, 10.5984, 10.5984, 10.5984, 1…
$ v0606 <chr> "1", "4", "4", "4", "1", "1", "1", "4", "1", "1", "1", "3", "1",…
$ v0601 <chr> "2", "1", "2", "1", "2", "1", "1", "1", "2", "1", "1", "1", "2",…

A partir do resultado obtido e da padronização adotada pelas funções do Tidyverse, é possível observar rapidamente a estrutura da tabela (552307 linhas/observações e 7 colunas/variáveis), o tipo de dado presente em cada coluna, bem como os primeiros valores para cada uma das variáveis.

Analisando os dados: um retrato para a escala municipal.

Com os dados em mãos, a investigação propriamente dita sobre o comportamento da questão racial pode ir adiante. Nesse sentido, inicialmente será computada a distribuição da variável raça/cor para todo o município. Em seguida, o mesmo procedimento será realizado, mas dessa vez considerando-se a escala de maior detalhe do dado: a área de ponderação. Nesse momento, procurar-se-á entender como a distribuição da raça/cor se dá em diferentes regiões do território paulistano. Por fim, serão identificadas e analisadas as áreas de ponderação que abrangem a região de interesse - e que serão descobertas mais à frente.

A seguir, inicia-se o cômputo para o município, como um todo. Para facilitar a interpretação, algumas transformações são realizadas na base (conversão de tipos de dados e criação de novas variáveis, por ex.).

Code
# Compute the RACE distribution by MUN
1race_by_mun_2010 <- micro_pop |>
  mutate(
    v0606 = factor(v0606),
    raca_cor_nome = factor(case_when(
      v0606 == 1 ~ "Branca",
      v0606 == 2 ~ "Preta",
      v0606 == 3 ~ "Amarela",
      v0606 == 4 ~ "Parda",
      v0606 == 5 ~ "Indígena", 
      v0606 == 9 ~ "Ignorado")) 
2        ) |>
3  group_by(v0606, raca_cor_nome) |>
4  summarise(tot_peop_peso = sum(v0010),  tot_peop_orig = dplyr::n()) |>
5  rename(raca_cor = v0606) |>
6  ungroup() |>
7  mutate(prop_race = 100* tot_peop_peso/sum(tot_peop_peso))

# See the result
8race_by_mun_2010
1
Selecione a base e crie um objeto para guardar as informações sobre raça/cor em todo o município de São Paulo;
2
Transforme o tipo da variável raça/cor (de character para fator) e crie uma nova variável (coluna). Neste caso, as categorias de raça/cor são codificadas com nomes (preta, indígena, branca, etc.), e não mais números;
3
Defina cada uma das raças/cores como grupos para as operações a seguir;
4
Compute as estimativas da população (tot_peop_peso) e o número de casos amostrados por grupo criado;
5
Renomeie a variável original de raça/cor (v0606);
6
Desagrupe os dados (caso queira entender o impacto desse passo, acrescente o símbolo de comentário no inicío dessa linha (“#”), indicando para o R que o dado deve continuar agrupado; rode o código e veja o resultado produzido);
7
Compute as proporções de pessoas para cada raça/cor e
8
Observe o resultado (quantidade e proporção de pessoas para cada raça/cor)

Os dados gerados permitem que se construa um primeiro retrato sobre o total de pessoas por raça/cor no município de São Paulo em 2010. A atual forma pode, contudo, ser alvo de melhorias. Assim sendo, propõe-s uma nova tabela para os dados recém-obtidos. Nela, como pode ser visto, existem menos variáveis, os nomes das variáveis são mais intuitivos (facilitando a leitura), os dados foram reordenados - do grupo com mais pessoas para o que possui menos - e ela é esteticamente mais atraente. Tais medidas, facilmente implementadas, ajudam a manter o foco no que realmente importa e facilitam a leitura e compreensão dos dados.

Nota

Tão relevante quanto a geração de dados é a comunicação dos achados - algo que, aos poucos e na medida do possível, será explorado no presente texto. Isso porque, caso a sua publicização não seja adequada, o impacto gerado, na melhor das hipóteses, deixará de atingir toda a sua potencialidade. Ou seja, não desconsidere esse fator!

Code
# Adjust and make a new table 
1race_by_mun_2010 |>
2  select(raca_cor_nome, tot_peop_peso, prop_race) |>
3  rename("Raça ou cor" = raca_cor_nome, "Total de pessoas" = tot_peop_peso, "Proporção (%)" = prop_race) |>
4  mutate(across(.cols = `Total de pessoas`, round)) |>
5  arrange(desc(`Proporção (%)`)) |>
6  gt()
1
Selecione a base de dados gerada;
2
Escolha apenas as variáveis de interesse;
3
Renomeie as variáveis;
4
Arrendonde os valores referentes ao total de pessoas;
5
Ordene os dados da maior proporção de pessoas para a menor, e,
6
Gere uma tabela mais visualmente atrativa;
Raça ou cor Total de pessoas Proporção (%)
Branca 6823004 60.630044
Parda 3447290 30.633035
Preta 717215 6.373257
Amarela 250146 2.222825
Indígena 12959 0.115152
Ignorado 2891 0.025688

Outra forma bastante interessante para a visualização de dados e compreensão daquilo que se quer entender baseia-se no uso de gráficos. Para o presente caso, a opção mais apropriada seria o gráfico de barras. E como forma de explorar parte dos elementos que podem compô-lo, optou-se por i) adotar um título, subtítulo e fonte, e, ii) modififcar os valores dos eixos e a cor de fundo. Saliente-se, porém, que o uso de cor fazendo referência às raças ou mesmo o título adotado (mais descritivo e geral) poderiam seguir estratégias distintas e talvez mais interessantes, a depender do contexto e objetivo perseguidos - enfatizando o grupo de interesse, por exemplo4.

Code
# Create a graphic for the race distribution
## Parameters to reuse
title_grap =  "Distribuição de pessoas por cor ou raça"
subtitle_grap =  "Município de São Paulo, 2010"
data_orig_grap = "IBGE, Censo 2010"
# ap_sel <- c(3550308005001, 3550308005007, 3550308005008)

## Municipality
1race_mun_graph <- race_by_mun_2010 |>
2  ggplot(aes(x = fct_reorder(raca_cor_nome, tot_peop_peso, .desc = T), y = tot_peop_peso, fill = raca_cor_nome)) +
3    geom_col(show.legend = F) +
    geom_text(aes(
      label = round(tot_peop_peso)),
      vjust = - 0.5,
      hjust = 0.5,
      size = 4,
      fontface = "bold",
      # colour = "#3b3938"
4      ) +
    geom_text(aes(
      label = str_c("(", round(prop_race, 2), "%)")),
      vjust = 1.25,
      hjust = 0.5,
5      size = 3.5) +
    labs(title = title_grap,
       subtitle = subtitle_grap,
       caption = data_orig_grap,
       # x = "(Cor ou raça)",
       # y = "(Número de pessoas)"
6       )  +
7  scale_fill_manual(values = c("yellow", "#fee6ce", "lightgrey", "#bf812d", "#8c510a", "#5e3814")) +
  scale_y_continuous(breaks = c(0, 2000000, 4000000, 6000000),
8                    labels = c("0", "2 Mi", "4 Mi", "6 Mi")) +
  # scale_fill_viridis_d(direction = 1) +
9  theme_classic(base_size = 14) +
  theme(
    axis.ticks.x = element_blank(),
    # axis.text.x = element_blank(),
    axis.ticks.y = element_blank(),
    # axis.text.y = element_blank(),
    axis.title = element_blank() # element_text(colour = "grey", size = 7.5))  
    )

# Look the graphic
10race_mun_graph
1
Defina qual será a base utilizada para a criação do gráfico e crie um objeto para salvar o resultado gerado a seguir;
2
Selecione quais variáveis serão expostas no gráfico (eixos x e y);
3
Escolha o gráfico de barras como opção de representação;
4
Defina a localização dos totais de pessoas nas barras;
5
Defina a localização da proporção de pessoas nas barras;
6
Defina quais serão o título, subtítulo e fonte;
7
Defina cores específicas para cada uma das raças (barras);
8
Defina novos intervalos para o eixo y (total de pessoas);
9
Escolha como o fundo e os elementos dos eixos devem ser visualizados, e,
10
Apresente o gráfico.

A partir da tabela e do gráfico, verifica-se, por exemplo, que cerca de 3/5 (60,6%) da população paulistana se autodeclarou branca em 2010. A população negra (parda + preta), por sua vez, respondeu por 37% de todos os paulistanos e paulistanas. No extremo oposto encontram-se as pessoas com algum tipo ascendência dos povos asiáticos (amarelos) e à população indígena. Presentes em nosso território antes da colonização europeia, os povos originários do Brasil representavam apenas 0,1% dos e das paulistanas em 2010, totalizando quase treze mil pessoas.

Analisando os dados: avançando no entendimento sobre a distribuição da raça/cor nas diferentes partes do território municipal (áreas de ponderação)

De forma a aprofundar o conhecimento sobre a área de interesse aqui tratada (região da Liberdade), a partir desse momento passa-se a explorar a distribuição da raça/cor por área de ponderação. Ao revisitar a temática em uma escala mais detalhada, comparações entre regiões tornam-se possíveis, com novos subsídios e/ou padrões podendo ser revelados (para o município e para a área de interesse).

A seguir, o código gera a distribuição da população por raça/cor para cada uma das áreas de ponderação do município de São Paulo.

Code
# Compute the RACE distribution by AP
race_by_ap_2010 <- micro_pop |>
  mutate(v0606 = factor(v0606),
         v0011 = factor(v0011)
         ) |>
  group_by(v0011, v0606, .drop = FALSE) |> 
  summarise(tot_peop_peso = sum(v0010), tot_peop = n()) |>
  mutate(prop_race = 100*tot_peop_peso/sum(tot_peop_peso),
         raca_cor_nome = factor(case_when(
           v0606 == 1 ~ "Branca",
           v0606 == 2 ~ "Preta",
           v0606 == 3 ~ "Amarela",
           v0606 == 4 ~ "Parda",
           v0606 == 5 ~ "Indígena",
           v0606 == 9 ~ "Ignorado"))
         ) |> 
  relocate(ap = v0011, raca_cor = v0606, raca_cor_nome) 
`summarise()` has grouped output by 'v0011'. You can override using the
`.groups` argument.
Code
# Show the result
race_by_ap_2010
# A tibble: 1,860 × 6
# Groups:   ap [310]
   ap            raca_cor raca_cor_nome tot_peop_peso tot_peop prop_race
   <fct>         <fct>    <fct>                 <dbl>    <int>     <dbl>
 1 3550308005001 1        Branca               13619.      710     57.6 
 2 3550308005001 2        Preta                  978.       49      4.14
 3 3550308005001 3        Amarela               1921.       95      8.12
 4 3550308005001 4        Parda                 7133.      359     30.2 
 5 3550308005001 5        Indígena                 0         0      0   
 6 3550308005001 9        Ignorado                 0         0      0   
 7 3550308005002 1        Branca               15653.      764     69.9 
 8 3550308005002 2        Preta                 1360.       62      6.07
 9 3550308005002 3        Amarela                588.       26      2.63
10 3550308005002 4        Parda                 4786.      240     21.4 
# ℹ 1,850 more rows

O resultado produzido está no que se costuma chamar de base ou tabela de forma longa. Mais adequada para a manipulação de dados, percebe-se que para cada área de ponderação são apresentadas todas as categorias da variável raça/cor, dispostas verticalmente, bem como os seus valores. Tomando-se como exemplo a primeira área de ponderação, 3550308005001, verifica-se que a primeira linha é destinada à raça branca, a segunda à preta, a terceira à amarela e assim por diante. Essa disposição é, então, retomada quando se inicia a segunda área de ponderação, 3550308005002, com a sétima linha apresentando os dados para a raça branca, a oitava para a raça preta, etc. Tal forma, saliente-se, nem sempre facilita a visualização e o entendimento do que se quer investigar.

Tendo isso em vista, a seguir os mesmos dados serão apresentados a partir da chamada forma ampla ou larga. Como poderá ser visto, dessa vez cada área de ponderação ocupa apenas uma linha da tabela. As categorias da variável raça/cor, por sua vez, são transpostas para as colunas.

Code
# Transpose the data into a wider table   
1race_by_ap_2010_wider <- race_by_ap_2010 |>
2  pivot_wider(id_cols = ap, names_from = raca_cor, values_from = c(tot_peop_peso, prop_race)) |>
3  set_names("ap", "branca", "preta", "amarela", "parda", "indigena", "ignorado", "branca_prop",  "preta_prop", "amarela_prop", 'parda_prop',  "indigena_prop", "ignorado_prop") |>
4  relocate("ap", "branca",  "parda", "preta", "amarela", "indigena", "ignorado", "branca_prop", 'parda_prop',  "preta_prop", "amarela_prop",  "indigena_prop", "ignorado_prop") |>
5  ungroup() |>
6  mutate(tot_pop = branca + parda + preta + amarela + indigena + ignorado)


# See the first version of the wider table
7race_by_ap_2010_wider

# Look only to the number of people (absolute values) by AP and race
8head(race_by_ap_2010_wider[c(1:7, 14)], n = 10) |>
  mutate(across(.cols = !ap, .fns = round)) |> 
  rename(Branca = branca, Parda = parda, Preta = preta, Amarela = amarela, `Indígena` = indigena, Ignorado = ignorado, Total = tot_pop) |> 
  gt(rowname_col = "ap")

# Now consider only the proportion of people (relative values) by AP and race
9head(race_by_ap_2010_wider[c(1, 8:14)], n = 10) |>
  rename(`Branca (%)` = branca_prop, `Parda (%)` = parda_prop, `Preta (%)` = preta_prop, `Amarela (%)` = amarela_prop, `Indígena (%)` = indigena_prop, `Ignorado (%)` = ignorado_prop, Total = tot_pop) |>
  gt(rowname_col = "ap")
  
# write_csv2(race_by_ap_2010_wider, file = here(file.path("2010", "Gerados", "Tabelas", "raca_ap_sp_2010.csv")))
1
Selecione a base e crie um objeto para salvar os dados em formato longo;
2
Transforme as categorias da variável raça/cor, originalmente empilhadas, em colunas;
3
Adote novos nomes (mais intuitivos) para as colunas;
4
Mude a ordem das colunas;
5
Desagrupe os dados;
6
Crie uma coluna e compute a população total das AP (soma de todas as raças mais os casos “ignorado”);
7
Observe os dados dispostos na nova forma e note que a base apresenta tanto os dados absolutos quanto os relativos;
8
Observe os resultados para as dez primeiras áreas de ponderação, considerando apenas o número de pessoas (volume) para cada cor/raça (perceba o arredondamento dos valores praticado), e,
9
Observe os resultados para as dez primeiras áreas de ponderação, mas agora considerando apenas a proporção de pessoas para cada cor/raça.
# A tibble: 310 × 14
   ap        branca parda preta amarela indigena ignorado branca_prop parda_prop
   <fct>      <dbl> <dbl> <dbl>   <dbl>    <dbl>    <dbl>       <dbl>      <dbl>
 1 35503080… 13619. 7133.  978.   1921.      0          0        57.6       30.2
 2 35503080… 15653. 4786. 1360.    588.      0          0        69.9       21.4
 3 35503080… 22803. 8443. 1531.   1644.    171.         0        65.9       24.4
 4 35503080… 17379. 8837. 1622.   5675.    379.         0        51.3       26.1
 5 35503080… 18996. 8334. 1049.    829.     56.5        0        64.9       28.5
 6 35503080… 27442. 6309. 1212.   1962.     22.7        0        74.3       17.1
 7 35503080… 28848. 4790. 1045.   5697.     20.0        0        71.4       11.9
 8 35503080… 16871. 4180.  676.   6940.     25.4        0        58.8       14.6
 9 35503080… 13897. 3394.  680.    610.     25.3        0        74.7       18.2
10 35503080… 22012. 4791. 1412.   2564.      0          0        71.5       15.6
# ℹ 300 more rows
# ℹ 5 more variables: preta_prop <dbl>, amarela_prop <dbl>,
#   indigena_prop <dbl>, ignorado_prop <dbl>, tot_pop <dbl>
Branca Parda Preta Amarela Indígena Ignorado Total
3550308005001 13619 7133 978 1921 0 0 23651
3550308005002 15653 4786 1360 588 0 0 22388
3550308005003 22803 8443 1531 1644 171 0 34593
3550308005004 17379 8837 1622 5675 379 0 33892
3550308005005 18996 8334 1049 829 57 0 29265
3550308005006 27442 6309 1212 1962 23 0 36948
3550308005007 28848 4790 1045 5697 20 0 40400
3550308005008 16871 4180 676 6940 25 0 28692
3550308005009 13897 3394 680 610 25 0 18606
3550308005010 22012 4791 1412 2564 0 0 30780
Branca (%) Parda (%) Preta (%) Amarela (%) Indígena (%) Ignorado (%) Total
3550308005001 57.584 30.160 4.1356 8.1202 0.000000 0 23651
3550308005002 69.919 21.378 6.0749 2.6286 0.000000 0 22388
3550308005003 65.917 24.407 4.4265 4.7538 0.495077 0 34593
3550308005004 51.278 26.075 4.7846 16.7437 1.118900 0 33892
3550308005005 64.910 28.479 3.5859 2.8323 0.193212 0 29265
3550308005006 74.273 17.075 3.2793 5.3109 0.061323 0 36948
3550308005007 71.406 11.857 2.5855 14.1019 0.049623 0 40400
3550308005008 58.802 14.567 2.3558 24.1863 0.088484 0 28692
3550308005009 74.692 18.239 3.6551 3.2777 0.136077 0 18606
3550308005010 71.515 15.566 4.5888 8.3301 0.000000 0 30780

A partir das últimas tabelas, que apresetam os valores absolutos (número total/volume/montante de pessoas) e relativos (proporção de pessoas), verifica-se uma disposição dos dados mais amigável. Um desafio persiste, porém: o município de São Paulo é composto por 310 áreas de ponderação. Ou seja, a tabela é constituída por 310 linhas, tornando a apreensão do todo difícil.

Em situações desse tipo, com bases de dados extensas, usualmente recorre-se a estratégias para sintetizá-los e explicitar eventuais padrões. Uma delas, inclusive, já foi explorada: o uso de ferramentas baseadas em visualização de dados, como os gráficos. A ela, some-se a geração de medidas síntese de localização, tal qual a famigerada média, e de dispersão, dentre as quais uma das mais conhecidas é o desvio padrão.

A seguir, dois tipos de gráficos (“pontos” e “boxplot + violino”) e uma tabela (composta por medidas de resumo) serão apresentados. Mais do que replicar as mesmas informações em formatos distintos, o que se espera é que eles se complementem e possibilitem uma leitura mais rica e acurada.

Iniciando a exploração com os gráficos, forma mais intuitiva, almeja-se verificar se alguns indícios ou padrões revelam-se a partir de uma análise visual. A partir das intuições encontradas e/ou questionamentos levantados (lembre-se: os questionamentos são a base da ciência!), em um segundo momento serão computados elementos “mais precisos” (estatísticas) para uma melhor descrição e caracterização da distribuição espacial da raça/cor, agregados em formato de tabela.

Code
# Create a graphic representing the race distribution with a dot plot (here, some noise is added)
graf_race_ap_2010_pnt0 <- race_by_ap_2010 |>
  ggplot(aes(x = fct_rev(fct_reorder(raca_cor_nome, tot_peop_peso, median)), y = tot_peop_peso)) +
    geom_point(alpha = 0.4, shape = 1) + 
    labs(x = NULL,
         y = NULL) +
    theme_classic(base_size = 14) +
    theme(
      # axis.ticks.x = element_blank(),
      axis.ticks.y = element_blank()) +
  coord_flip()


# Create a graphic representing the race distribution with a dot plot
1graf_race_ap_2010_pnt <- race_by_ap_2010 |>
2  ggplot(aes(x = fct_rev(fct_reorder(raca_cor_nome, tot_peop_peso, median)), y = tot_peop_peso)) +
3    geom_point(position = 'jitter', alpha = 0.4, shape = 1) +
    labs(x = NULL,
4         y = NULL) +
5    theme_classic(base_size = 14) +
    theme(
      # axis.ticks.x = element_blank(),
      axis.ticks.y = element_blank()) +
6  coord_flip()

# Create a graphic representing the race distribution with a violin and boxplot
graf_race_ap_2010_res <- race_by_ap_2010 |>
  ggplot(aes(x = fct_rev(fct_reorder(raca_cor_nome, tot_peop_peso, median)), y = tot_peop_peso)) +
    geom_boxplot() +
    geom_violin(scale = "width", fill = NA, color = "darkorange", alpha = 0.7) +
    labs(x = NULL,
         y = NULL) +
    theme_classic(base_size = 14) +
    theme(
      # axis.ticks.x = element_blank(),
      axis.ticks.y = element_blank()) +
  coord_flip()
    

# Plot and compare both graphics
7(graf_race_ap_2010_pnt0 / graf_race_ap_2010_pnt / graf_race_ap_2010_res)
1
Selecione a base de dados e crie um objeto para salvar o gráfico;
2
Defina quais serão as variáveis que aparecerão no gráfico;
3
Escolha o tipo de gráfico/representação dos dados. Note: nos dois primeiros casos, gera-se um gráfico de pontos, com os dados do segundo levemente deslocados. Já no segundo apresenta-se uma sobreposição entre o gráfico de violino e boxplot;
4
Exclua o nome dos eixos dos gráficos;
5
Defina alguns elementos visuais do gráfico, como o tamanho das letras, a cor do fundo e a exclusão dos pequenos traços que ligam os valores aos eixos;
6
Inverta o eixo dos gráficos, e,
7
Defina a ordem em que os gráficos serão dispostos.

Como pode ser visto, três gráficos são apresentados. Note-se, contudo, que tanto o primeiro quanto o segundo tratam de um mesmo tipo de representação (gráfico de pontos). Neles, os pontos indicam qual é a população total de cada uma das áreas de ponderação por raça/cor - a diferença, aqui explorada para fins didáticos, reside no fato do segundo gráfico apresentar dados ligeiramente deslocados de seu valor real, uma técnica usada para facilitar a análise e a apreensão de padrões.

Obervando-se a localização dos pontos, verifica-se, por exemplo, que enquanto as populações preta, indígena e amarela apresentam valores mais concentrados (maior número de pontos próximos e/ou sobrepostos, reforçando a cor preta), no caso das populações pardas e branca o total de pessoas nas áreas de ponderação está mais disperso (há uma maior variabilidade). Grosso modo, poder-se-ia dizer que o tamanho das populações preta, indígena e amarela, por área de ponderação, é mais parecido do que o encontrado para as populações branca e parda.

Considerando-se essa mesma separação, é seguro afirmar que todas as áreas de ponderação do município de São Paulo (ponto preto) possuem menos de 10.000 habitantes pretos, indígenas ou amarelos - limiar ultrapassado pelos residentes brancos e pardos em várias áreas de ponderaçao. Também é possível notar que, diferentemente de todas as outras populações, as áreas de ponderação com o menor número de pessoas brancas somam cerca de 10.000 pessoas - exceção feita a dois casos.

O segundo gráfico, composto pela sobreposição entre o gráfico de violino (linha laranja) e o boxplot , busca representar a distribuição da população, por raça/cor e áreas de ponderação, de outra forma. Iniciando-se a leitura pelo boxplot, destaque-se que alguns elementos dessa representação costumam ser sempre observados. Um deles é a sua caixa, que perfaz a metade central de todo o conjunto dos dados. Com isso, é possível estimar, por exemplo, que metade da população branca varia entre 16 e 26 mil pessoas, considerando-se a sua distribuição por área de ponderação. Já no caso da população parda esses valores parecem variar entre 5.000 e 15.000 pessoas (não se preocupe com a precisão nesse momento, pois os números corretos serão observados na tabela produzida mais adiante).

O boxplot fornece, ainda, ao menos duas outras informações interessantes. A primeira diz respeito à linha vertical central da caixa, que indica onde se encontra a mediana. Ordenando-se os totais das populações do menor para o maior valor, a mediana é o valor que divide o conjunto de dados ao meio5. No caso da população preta, por exemplo, esse valor parece estar próximo a 2.500 pessoas.

A outra informação de interesse está relacionada aos pontos que aparecem para algumas raças/cores. Neste caso, eles indicam as áreas de ponderação cuja população é muito diferente de todo o restante - esses casos são chamados de pontos discrepantes ou outliers. Percebe-se, por exemplo, que a raça amarela possui algumas áreas de ponderação com uma população muito maior do que o comportamento geral dessa raça no município. Já no extremo oposto encontra-se a populaçao preta, que não apresenta nenhuma área de ponderação que foge do comportamento geral dessa raça/cor.

Complementando os achados do boxplot, novos elementos obtidos por meio do gráfico de violino podem ser acrescentados. Ao representar de forma mais contínua a distribuição das populações por raça/cor e área de ponderação, é possível notar, por exemplo, que a população parda apresenta dois pequenos picos, um logo abaixo de 5.000 pessoas e outro em torno de 14.000 pessoas. As populações preta e branca, por sua vez, parecem apresentar um único pico. Com um olhar um pouco mais treinado, também é possível notar uma ligeira concentração de casos antes da mediana para essas raças/cores - compare o tamanho das caudas do gráfico antes e depois da linha da mediana.

De forma a tornar mais precisos os indícios, intuições e questões gerados a partir da visualização dos dados e avançar na busca de novos achados, a seguir serão computadas algumas estatísticas para cada uma das raças. Os resultados, por sua vez, são agrupados em uma mesma tabela.

Code
# Compute some metrics to describe the data
## Compute the measures by race
1branca_mtrc <- summary(race_by_ap_2010_wider$branca)
parda_mtrc <- summary(race_by_ap_2010_wider$parda)
preta_mtrc <- summary(race_by_ap_2010_wider$preta)
amarela_mtrc <- summary(race_by_ap_2010_wider$amarela)
indigena_mtrc <- summary(race_by_ap_2010_wider$indigena)
ignorado_mtrc <- summary(race_by_ap_2010_wider$ignorado)

## Create a table with all race metrics
2tab_race_metrcs_ap <- bind_rows(branca_mtrc, parda_mtrc, preta_mtrc, amarela_mtrc, indigena_mtrc, ignorado_mtrc) |>
3  as.data.frame() |>
  mutate(raca_cor = c("Branca", "Parda", "Preta", "Amarela", "Indigena", "Ignorado"),
4         across(.cols = !raca_cor, .fns = round)) |>
5  relocate(raca_cor) |>
6  set_names("Raça ou cor", "Menor valor", "1o. Quartil", "Mediana", "Média", "3o. Quartil", "Maior valor")

tab_race_metrcs_ap |> 
7  gt(rowname_col = "Raça ou cor")
1
Compute algumas métricas para cada uma das raças/cores;
2
Junte todas as métricas calculadas (“colando” as linhas);
3
Transforme a junção anterior em um data.frame (“tabela”);
4
Acrescente uma variável para a raça/cor e arredonde os valores da população;
5
Coloque a variável raça/cor na primeira posição da base, e,
6
Defina nomes mais intuitivos para as variáveis, e,
7
Crie uma tabela mais visualemente atrativa.|
Menor valor 1o. Quartil Mediana Média 3o. Quartil Maior valor
Branca 4160 17078 21362 22010 26572 42376
Parda 720 5276 11051 11120 15784 30592
Preta 82 1274 2264 2314 3186 6208
Amarela 19 238 494 807 941 6940
Indigena 0 0 22 42 48 1005
Ignorado 0 0 0 9 0 1231

A partir dos valores da tabela, verifica-se que as percepções obtidas por meio dos gráficos é corroborada pelos números. Um dos achados obtidos visualmente indicava uma maior concentração dos valores das populações preta, amarela e indígena por área de ponderação - levando, a grosso modo, à noção de que a distribuição dessas raças ao longo do território era mais parecido (ou menos diferente) do que o encontrado para as raças brancas e parda. Recorrendo-se ao Intervalo Interquaril (IQR) para quantificar esse comportamento6, constata-se que a diferença das populações por área de ponderação para as raças branca e preta é de 9.494 e 10.508 pessoas, respectivamente. Por sua vez, ao se considerar as populações preta, amarela e indígena, essa diferença é de 1.912, 703 e 48 pessoas. Ou seja, mesmo considerando-se a diferença entre a população branca (menor valor do grupo mais disperso, de acordo com o IQR) e a população preta (maior valor do grupo mais concentrado), a dispersão ou variabilidade é cinco vezes maior a favor da raça branca (9.494 pessoas brancas/1.912 pessoas pretas).

Observando-se as menores quantidades de pessoas por raça/cor presentes nas áreas de ponderação (coluna “Menor valor” da tabela), percebe-se que enquanto existe ao menos uma área de ponderação que não possui indígenas - valor que salta para ao menos 25% das áreas de ponderação, dado que o valor do 1º quartil é 07 -, o menor número de pessoas brancas em uma área de ponderação no município é de 4.160. Esse valor, aliás, é maior do que o encontrado em ao menos 75% de todas as áreas de ponderação para as raças/cores preta, amarela e indígena (observe e compare os dados a partir da coluna do 3º quartil).

Em sentido oposto, ao se considerarem as maiores quantidades de pessoas por raça/cor e área de ponderação (coluna “Maior valor”), agora é possível mensurar e identificar as áreas que possuem as maiores populações preta (6.208 pessoas), amarela (6.940) e indígena (1.005). Dado que a simples comparação desse valor com o do 3º quartil para cada uma dessas raças/cores indica uma diferença não desprezível, pode-se aventar ou suspeitar que algo ocorreu/ocorre nessas porções do território, fomentando essa concentração espacial.

Operando-se de forma similar, verifica-se que as estatísticas da tabela especificam as medidas anteriormente obtidas por meio dos gráficos. Dessa forma, as aproximações geradas para os percentis 25º e 75º (medidas/linhas limites da caixa do boxplot), bem como para o 50º (mediana, representanda pela linha dentro da caixa), agora são mensuradas e localizadas de forma mais precisa. No caso da população preta, por exemplo, o primeiro, o segundo (mediana) e o terceiro quartis correspondem a 1.274, 2.264 e 3.186 pessoas. Por sua vez, essas mesmas medidas para a população parda perfazem 5.276, 11.051 e 11.120 pessoas.

Para finalizar essa etapa de “contextualização regional”, duas novas estratégias serão rapidamente exploradas. Enquanto a primeira está baseada no tamanho das áreas de ponderação, como um todo (ou seja, considerando todas as raças/cores), a segunda abordará a questão a partir do tamanho da população negra (pessoas pardas + pessoas pretas).

O código a seguir fornece subsísios para a análise das áreas de ponderação (AP) mais populosas. O objetivo será compreender a composição por raça/cor para as cinco áreas com os maiores números de residentes - o número 5 foi escolhido para tornar a análise mais paupável e inteligível a partir dos dados brutos. Note-se, ainda, que um ranqueamento foi criado para auxiliar a leitura.

Code
# Select only the absolute values and rank all the race categories
1race_by_ap_2010_wider_pos_abs <- race_by_ap_2010_wider |>
2  select(!ends_with("_prop")) |>
3  mutate(branca_rank = min_rank(desc(branca)),
         parda_rank = min_rank(desc(parda)),
         preta_rank = min_rank(desc(preta)),
         amarela_rank = min_rank(desc(amarela)),
         indigena_rank = min_rank(desc(indigena)),
         total_rank = min_rank(desc(tot_pop)),
         across(.cols = !c(ends_with("_rank"), starts_with("ap")), .fns = round)) |>
4  rename(total = tot_pop) |>
5  arrange(desc(total))

tab_race_ap5_abs <- race_by_ap_2010_wider_pos_abs |> 
6  slice_head(n = 5)

tab_race_ap5_abs |>
7  set_names("AP", "Branca", "Parda", "Preta", "Amarela", "Indígena", "Ignorado", "Total", "Branca (Rank)", "Parda (Rank)", "Preta (Rank)", "Amarela (Rank)", "Indígena (Rank)", "Total (Rank)") |>
  # mutate(Negra = Parda + Preta) |>
  # relocate(Negra, .after = Preta) |>
8  gt()


# Select only the proportion values and rank all the race categories
9race_by_ap_2010_wider_pos_prop <- race_by_ap_2010_wider |>
  select(ap, ends_with("_prop"), tot_pop) |> 
  # left_join(race_by_ap_2010_wider_pos_abs[c("ap", "total")], join_by(ap)) |>
  # relocate(.after = ignorado_prop, total) |>   
  mutate(branca_prop_rank = min_rank(desc(branca_prop)),
         parda_prop_rank = min_rank(desc(parda_prop)),
         preta_prop_rank = min_rank(desc(preta_prop)),
         amarela_prop_rank = min_rank(desc(amarela_prop)),
         indigena_prop_rank = min_rank(desc(indigena_prop)),
         total_rank = min_rank(desc(tot_pop))) |>
  rename(total = tot_pop) |> 
  arrange(desc(total))

tab_race_ap5_prop <- race_by_ap_2010_wider_pos_prop |> 
  slice_head(n = 5) 

tab_race_ap5_prop |>
  set_names("AP", "Branca %", "Parda %", "Preta %", "Amarela %", "Indígena %", "Ignorado %", "Total", "Branca % (Rank)", "Parda % (Rank)", "Preta % (Rank)", "Amarela % (Rank)", "Indígena % (Rank)", "Total % (Rank)") |>
  # mutate(`Negra %` = `Parda %` + `Preta %`) |>
  # relocate(`Negra %`, .after = `Preta %`) |>
  gt()
1
Selecione a base de interesse e crie um objeto para salvar os resultados;
2
Selecione apenas as variáveis que apresentam os totais populacionais por raça/cor (todas aquelas que não terminavam com “_prop”);
3
Ranqueie, considerando a população total, as áreas de ponderação (AP) para cada uma das raça/cores ;
4
Adote nomes mais intuitivos para as variáveis;
5
Ordene as AP em função do tamanho de suas populações totais;
6
Selecione as cinco primeiras AP (mais populosas);
7
Defina nomes de variáveis mais intuitivas;
8
Gere uma tabela mais visualmente atrativa, e,
9
Repita o mesmo procedimento, mas agora considerando as proporções populacionais por raça/cor e área de ponderação.
AP Branca Parda Preta Amarela Indígena Ignorado Total Branca (Rank) Parda (Rank) Preta (Rank) Amarela (Rank) Indígena (Rank) Total (Rank)
3550308005259 23107 28449 5200 233 0 0 56989 127 2 5 236 201 1
3550308005189 24431 24757 6208 219 124 0 55739 99 3 1 242 22 2
3550308005280 25903 23058 4934 157 39 1231 55321 86 10 8 273 100 3
3550308005135 25197 24448 4172 206 101 0 54124 91 4 24 246 32 4
3550308005237 28194 20455 3783 856 79 0 53366 53 33 44 93 43 5
AP Branca % Parda % Preta % Amarela % Indígena % Ignorado % Total Branca % (Rank) Parda % (Rank) Preta % (Rank) Amarela % (Rank) Indígena % (Rank) Total % (Rank)
3550308005259 40.546 49.920 9.1242 0.40968 0.000000 0.000 56989 294 21 52 273 201 1
3550308005189 43.831 44.417 11.1380 0.39247 0.221855 0.000 55739 265 62 14 276 44 2
3550308005280 46.822 41.681 8.9181 0.28397 0.069949 2.225 55321 237 84 57 298 139 3
3550308005135 46.554 45.170 7.7080 0.38137 0.187363 0.000 54124 242 58 92 280 58 4
3550308005237 52.831 38.329 7.0879 1.60389 0.148234 0.000 53366 199 111 119 132 71 5

A partir dos dados gerados, verifica-se que as cinco áreas de ponderação (AP) mais populosas do município de São Paulo variam de 56989 a 53366 pessoas (com uma média de 55107.8 pessoas). E tal qual ocorre no município, as raças branca e parda concentram os maiores quantitativos de pessoas (cerca de 61 e 31) nessas áreas, sendo seguidas mais de longe pela pessoas pretas, amarelas e indígenas.

Ressalte-se, contudo, que a distância encontrada nesses casos é bem menor. Computando-se duas medidas de tendência central, constata-se que os totais médio e mediano de pessoas brancas dessas cinco AP são de 25366 e 25197. Já no caso das pessoas pardas, eles correspondem a 24233 e 25197.

Também é possível verificar que nas duas AP com o maior número de residentes do município (3550308005259 e 3550308005189) ocorre uma inversão entre as raças/cores branca e parda. Totalizando 49,9% (28.449 pessoas) e 44,4% (24.747), a população parda ali presente supera a branca - a leitura espacial a seguir indicará que essas duas AP estão localizadas nos distritos do Lajeado, extremo leste do município, e da Brasilândia, na Zona Norte. Mais: caso se considere a população negra (preta + parda), das cinco AP mais populosas, apenas a 3550308005237 possui mais residentes brancos - com 53% de brancos e 45% de negros, essa área está localizada no distrito do Campo Limpo. Para as quatro AP restantes, os números da população negra variam de 51% do total a 59% (27.992 a 33.649 pessoas, respectivamente).

Feitos esses breves comentários, passa-se, agora, a alguns breves comentários baseados no ranqueamento das raças/cores para as cinco AP analisadas. Antes, contudo, é importante reforçar que o ordenamento e a classificação foram realizados do maior valor (que ocupa a posição 1) para o menor (que ocupa a posição 310). Com isso, torna-se possível “olhar para dentro” de cada raça/cor e entender a sua distribuição territorial específica.

Consideranço-se apenas os totais populacionais (valores absolutos), verifica-se, de forma geral, que as cinco AP mais populosas também apresentam grandes contingentes de pessoas pardas e negras . Observa-se, por exemplo, que quatro das cinco AP mais populosas do município estão entre as 10 AP mais pardas do município (posições 2, 3, 4 e 10). No caso da população preta, o mesmo ocorre para três dos cinco casos analisados (posições 1, 8 e 5). Apenas para efeito de comparação, a AP que possui o maior número de pessoas brancas (28.194) dentre as 5 AP mais populosas do município ocupa apenas a posição 51 no ranking de AP da raça/cor branca.

A seguir, as cinco AP analisadas são espacializadas e inseridas dentro dos seus respectivos distritos (limites em roxo e linha preta). Localizadas em diferentes partes do território (zonas Leste, Norte e Sul), percebe-se com relativa facilidade um traço comum: todas se encontram em regiões periféricas do município. Note: para além da legenda, localizada no canto direito superior do “mapa”, no canto inferior direito aparece a identificação dessas AP novamente. Esse “botão translúcido”, ao ser clicado, leva a um zoom da área escolhida no mapa. Para retornar ao zoom inicial, clique no botão no canto inferior esquerdo (Zoom full).

Code
# Select the 1st five AP with the highest population
## Get the AP spatial limits
ap_mun_sp <- read_weighting_area(code_weighting = 3550308, year = 2010)
Using year/date 2010
Code
## Find out the code of the 1st five AP with the highest population from the aspatial data set
top5_ap_abs <- race_by_ap_2010_wider_pos_abs |> 
  slice_head(n = 5) 
# |>  pull(ap)

## Filter the 1st 5 AP spatial limits of interest 
ap_top5_pop_geo <- ap_mun_sp |> 
  select(code_weighting, name_muni) |> 
  right_join(top5_ap_abs, join_by(code_weighting == ap)) |> 
  relocate(name_muni) |> 
  arrange(desc(total))

ap_top5_pop_geo_pts <- ap_top5_pop_geo |>
  st_centroid()


# Get the district spatial limits for SP munic
distrito_mun_sp <- read_neighborhood(year = 2010) |>
  filter(code_muni == 3550308) |> 
  select(abbrev_state, name_muni, code_district, name_district)
Using year/date 2010
Code
# See both AP selected and District data together in the space
## See the color pallets available
display.brewer.all(n = NULL, type = "all", select = NULL, exact.n = TRUE, 
                   colorblindFriendly = TRUE)

Code
## Create a map to show the AP limits
map_top5_ap_pop_lim <- mapview(distrito_mun_sp, 
                               zcol = "name_district", 
                               color = "gray35", 
                               col.regions = "royalblue", 
                               alpha.regions = 0.4, 
                               legend = FALSE) + 
  mapview(ap_top5_pop_geo, 
          zcol = "code_weighting", 
          lwd = 2, 
          burst = T)  

## Create a map to show the AP centroids/points
map_top5_ap_pop_pts <- mapview(distrito_mun_sp, 
                               zcol = "name_district", 
                               color = "gray35", 
                               col.regions = "royalblue", 
                               alpha.regions = 0.4, 
                               legend = FALSE) + 
  mapview(ap_top5_pop_geo_pts, 
          zcol = "total", 
          cex = "total", 
          layer.name = "Pop (total)", 
          col.regions = brewer.pal(5, "YlOrRd"))

## Show both maps
leafsync::sync(map_top5_ap_pop_lim, map_top5_ap_pop_pts, ncol = 2)

Para o desenvolvimento da segunda estratégia, propõe-se uma leitura mais integrada entre os dados e sua distribuição espacial. Mais do que formalizar ou representar de outra forma os achados, agora a espacialização contribuirá mais ativamente para a produção de subsídios e achados.

A seguir, serão computados e ordenados os totais e as proporções da população negra por área de ponderação, com destaque para as cinco maiores áreas/populações. Note: ainda que possa se basear no ranqueamento realizado anteriormente, de forma a explorar a construção de códigos um caminho distinto é proposto.

Code
# Select the 5 weighting areas (AP) with the highest black population (absolute values)
## Compute the total black population for all 310 AP
1tab_black_ap_abs <- race_by_ap_2010_wider_pos_abs |>
  mutate(negra = parda + preta,
2         negra_rank = min_rank(desc(negra)))  |>
3  relocate(negra, .after = preta) |>
  relocate(negra_rank, .after = preta_rank) |>
4  arrange(desc(negra))

## Select only the 5 AP with most Black population 
tab_black_ap5_abs <- tab_black_ap_abs |> 
5  head(5)

## Create a more attractive table
tab_black_ap5_abs |>   
6  select(!ends_with("_rank")) |>
7  set_names("AP", "Branca", "Parda", "Preta", "Negra", "Amarela", "Indígena", "Ignorado", "Total") |>
  # set_names("AP", "Branca", "Parda", "Preta", "Negra", "Amarela", "Indígena", "Ignorado", "Total", "Branca (Rank)", "Parda (Rank)", "Preta (Rank)", "Amarela (Rank)", "Indígena (Rank)", "Total (Rank)") |> 
8  gt()
  

# Select the 5 weighting areas with the highest proportion of black people (relative values)
## Compute the total black population for all 310 AP
9tab_black_ap_prop <- race_by_ap_2010_wider_pos_prop |>
  mutate(negra_prop = parda_prop + preta_prop,
         negra_prop_rank = min_rank(desc(negra_prop)))  |> 
  relocate(negra_prop, .after = preta_prop) |>
  relocate(negra_prop_rank, .after = preta_prop_rank) |>
  arrange(desc(negra_prop)) 

tab_black_ap5_prop <- tab_black_ap_prop |> 
  head(5)
  
# Create a more attractive table
tab_black_ap5_prop |>   
  select(!ends_with("_rank")) |> 
  mutate(across(!c(ap, total), .fns = ~round(x = ., digits = 2))) |> 
  set_names("AP", "Branca (%)", "Parda (%)", "Preta (%)", "Negra (%)", "Amarela (%)", "Indígena (%)", "Ignorado (%)", "Total") |> 
  # set_names("AP", "Branca", "Parda", "Preta", "Negra", "Amarela", "Indígena", "Ignorado", "Total", "Branca (Rank)", "Parda (Rank)", "Preta (Rank)", "Amarela (Rank)", "Indígena (Rank)", "Total (Rank)") |> 
  gt()
1
Selecione a base de interesse e crie um objeto para salvar os resultados;
2
Adicione duas novas variáveis, uma para a contagem da população negra (var negra) e a outra para o seu ranqueamento (var. negra_rank);
3
Desloque as variáveis criadas;
4
Ordene a base em função da população total negra de forma decrescente (do maior para o menor valor);
5
Selecione as cinco primeiras AP (cinco maiores populações negras);
6
Exclua as variáveis que tratam do ranqueamento para a criação de uma tabela mais limpa;
7
Defina nomes de variáveis mais intuitivas;
8
Gere uma tabela mais visualmente atrativa, e,
9
Repita o mesmo procedimento, mas agora considerando as proporções populacionais por raça/cor e área de ponderação.
AP Branca Parda Preta Negra Amarela Indígena Ignorado Total
3550308005259 23107 28449 5200 33649 233 0 0 56989
3550308005175 16957 30592 2855 33447 332 0 0 50736
3550308005189 24431 24757 6208 30965 219 124 0 55739
3550308005194 18399 24363 4318 28681 335 16 0 47431
3550308005135 25197 24448 4172 28620 206 101 0 54124
AP Branca (%) Parda (%) Preta (%) Negra (%) Amarela (%) Indígena (%) Ignorado (%) Total
3550308005290 30.40 59.56 9.72 69.28 0.31 0.00 0 32966
3550308005175 33.42 60.30 5.63 65.92 0.66 0.00 0 50736
3550308005289 33.79 57.05 8.60 65.65 0.37 0.19 0 30152
3550308005281 34.16 57.74 7.31 65.05 0.79 0.00 0 29088
3550308005292 35.05 55.22 9.17 64.39 0.51 0.05 0 43382

Para complementar a leitura a partir dos dados totais e proporcionais da população negra no município de São Paulo, a seguir eles são espacializados.

Code
# Join the AP limits (geospatial) with pop data by AP (aspatial)
ap_pop_black_abs_geo <- ap_mun_sp |> 
  select(name_muni, code_weighting) |> 
  right_join(tab_black_ap_abs, join_by(code_weighting == ap)) |> 
  arrange(desc(negra))

# Select the 5 highest black population by AP
ap_top5_pop_black_abs_geo <- ap_pop_black_abs_geo |> 
  head(5)

# Create the centroids of the 5 highest black population by AP
ap_top5_pop_black_abs_geo_pts <- ap_top5_pop_black_abs_geo |> 
  st_centroid()

# Map the black population by AP and show the 5 biggest pop/area
## Fill all the AP with black population
map_ap_pop_black_lim <- mapview(ap_pop_black_abs_geo, 
        zcol = "negra", 
        col.regions = brewer.pal(310, "YlOrRd"), 
        lwd = 0.15, 
        layer.name = "Pop. (Total)")

## Map the five AP with the highest Black population
map_top_5_ap_pop_black_pts  <- mapview(ap_top5_pop_black_abs_geo_pts, 
          zcol = "negra", 
          cex = "negra",
          color = "grey25",
          alpha.regions = 0, 
          lwd = 2,
          layer.name = "Pop. (5 mais)", 
          legend = F)

## Map the SP's district limits
map_distrito_mun_sp_lim <-  mapview(distrito_mun_sp, zcol = "name_district", alpha.regions = 0, lwd = 0.3, legend = FALSE)

## Join the three layers into a unique geospatial representation
map_black_abs_all <-map_ap_pop_black_lim +
  map_top_5_ap_pop_black_pts +
    map_distrito_mun_sp_lim

  
# Join the AP limits (geospatial) with pop data by AP (aspatial)
ap_pop_black_prop_geo <- ap_mun_sp |> 
  select(name_muni, ap = code_weighting) |> 
  right_join(tab_black_ap_prop, join_by(ap)) |> 
  mutate(across(.cols = !c("name_muni", "ap", "geom"), .fns = ~round(x = ., digits = 2))) |> 
  arrange(desc(negra_prop))

# Select the 5 highest black population by AP
ap_top5_pop_black_prop_geo <- ap_pop_black_prop_geo |> 
  head(5)

# Create the centroids of the 5 highest black population by AP
ap_top5_pop_black_prop_geo_pts <- ap_top5_pop_black_prop_geo |> 
  st_centroid()

# Map the black population by AP and show the 5 biggest pop/area
## Fill all the AP with black population
map_ap_pop_black_prop_lim <- mapview(ap_pop_black_prop_geo, 
        zcol = "negra_prop", 
        col.regions = brewer.pal(310, "YlOrRd"), 
        lwd = 0.15, 
        layer.name = "Pop. (%)")

## Map the five AP with the highest Black population
map_top_5_ap_pop_black_prop_pts  <- mapview(ap_top5_pop_black_prop_geo_pts, 
          zcol = "negra_prop", 
          cex = "negra_prop",
          color = "black",
          alpha.regions = 0, 
          lwd = 2,
          layer.name = "Pop. (% 5 most)", 
          legend = F)

## Join the three layers into a unique geospatial representation
map_black_prop_all <- map_distrito_mun_sp_lim + 
  map_ap_pop_black_prop_lim +
    map_top_5_ap_pop_black_prop_pts
    

# Show both maps side by side
leafsync::sync(map_black_abs_all, map_black_prop_all)

Analisando os dados: da identificação à caracterização da região de interesse

Conhecida a distribuição da questão racial para o município de São Paulo, como um todo, bem como entre regiões, o próximo passo consiste em observar a distribuição da questão racial em nossa área de interesse (região da Liberdade). O primeiro passo consiste em identificar quais são as áres de ponderação que abrangem a região. Recorrendo a um mapa interativo para essa finalidade, o objetivo será identificar, a partir da navegação espacial, quais são os códigos das áreas de ponderação qu recobrem a área de interesse.

Code
# Download the São Paulo weighting area limits    
1ap_mun_sp <- read_weighting_area(code_weighting = 3550308, year = 2010)
1
Baixe os limites das áreas de ponderação, definindo o município e o ano;
Using year/date 2010
Code
# Download the São Paulo district limits    
2distrito_mun_sp <- read_neighborhood(year = 2010) |>
  filter(code_muni == 3550308) |> 
  select(abbrev_state, name_muni, code_district, name_district)
2
Baixe os limites dos distritos, definindo o município, o ano e as variáveis de interesse, e,
Using year/date 2010
Code
# Plot the weighting areas and district limits
3mapview(ap_mun_sp, zcol = "code_weighting", legend = FALSE) + mapview(distrito_mun_sp, zcol = "name_district", alpha.regions = 0, legend = FALSE)
3
Plote os limites de ambos os dados.

Como pode ser visto, o recurso gerado possibilita não só a navegação digital pelo território - com o deslocamento pelas áreas da cidade e o uso do zoom -, mas também permite escolher a imagem de fundo e as camadas geoespaciais (áreas de ponderação e/ou distritos) a serem visualizadas. Para isso, basta clicar no botão com o desenho de retângulos empilhados no lado esquerdo superior da janela e realizar as escolhas. Note: os vazios e/ou a superposição entre polígonos da mesma camada são resultado apenas da opção para deixar a visualização mais leve. No dado original, contudo, eles não existem (em linguagem mais técnica, não há problemas de topologia).

A partir da interação com o mapa digital, verifica-se que três são as áreas de ponderação (AP) de interesse, com duas pertencendo ao distrito da Liberdade (3550308005007 e 3550308005008) e a outra ao distrito da Sé (3550308005001).

Footnotes

  1. Ainda que alguns dos principais elementos associados à exploração e análise introdutória de dados sejam abordados, não se pretende esgotar todos os elementos que venham a ser revelados. Longe de uma análise extensiva, o que se busca é construir uma lógica/estrutura para a exploração do fenômeno e/ou processo de interesse.↩︎

  2. Ainda que sejam mais usalmente utilizados, alguns dados censitários também são disponibilizados em outros formatos, como as grades estatísticas(https://mapasinterativos.ibge.gov.br/grade2022/default.html).↩︎

  3. Para identificar quais são, efetivamente, os dados disponibilizados para cada um dos censos, visite: https://ipeagit.github.io/censobr/articles/censobr.html.↩︎

  4. A discussão sobre visualização de dados e Storytelling com dados é vasta e não será aqui abordada de forma mais profunda. Uma referência bastante conhecida nesse campo é o livro de Cole N. Knaflic, Storytelling com dados.↩︎

  5. A mediana, diferentemente da média, é muito menos influenciada pela existência de valores discrepantes (outliers), motivo pelo qual é considerada uma medida de tendência central (ou, de forma mais ampla, medida de localização) robusta.↩︎

  6. o IQR é uma medida de dispersão robusta que computa a diferença entre os valores do primeiro e terceiro quartis dos dados.↩︎

  7. Observando-se a tabela com os dados brutos, nota-se que 110, das 310 áreas de ponderação do município de São Paulo, não possuem indígenas residentes (cerca de 35%).↩︎